/*
 * Copyright (C) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * created on : 2012-10-19
 * author : yanguoyue
 */

#include <node_api.h>
#include <vector>

#include "stn_logic_C2JS.h"
#include "mars/comm/autobuffer.h"
#include "mars/comm/xlogger/xlogger.h"
#include "mars/comm/napi/util/var_cache.h"
#include "mars/comm/napi/util/comm_function.h"
#include "mars/comm/compiler_util.h"
#include "mars/comm/platform_comm.h"
#include "mars/stn/stn.h"
#include "mars/stn/task_profile.h"
#include "mars/boost/signals2.hpp"

namespace mars {
namespace stn {

extern boost::signals2::signal<void (ErrCmdType _err_type, int _err_code, const std::string& _ip, uint16_t _port)> SignalOnLongLinkNetworkError;
extern boost::signals2::signal<void (ErrCmdType _err_type, int _err_code, const std::string& _ip, const std::string& _host, uint16_t _port)> SignalOnShortLinkNetworkError;


typedef struct{
  ExecData base;
  uint32_t taskid;
  void* const user_context;
  const std::string& user_id;
  int error_type;
  int& error_code;
  const ConnectProfile& profile;
  int result;
} OnTaskEndData;

int C2JS_OnTaskEnd(uint32_t taskid, void* const user_context, const std::string& user_id, int error_type, int error_code, const ConnectProfile& profile){
    xverbose_function();

    static bool schedule = true;
    xinfo2("enter C2JS_OnTaskEnd schedule:") << schedule;
    xdebug2(TSF"recieve task profile: %_, %_, %_", profile.start_connect_time, profile.start_send_packet_time, profile.read_packet_finished_time);

    if(schedule) {
        OnTaskEndData data = {NULL, taskid, user_context, user_id, error_type, error_code, profile};
        data.base.jsfn = [](void* data){
            OnTaskEndData* p = (OnTaskEndData*)data;
            schedule = false;
            p->result = C2JS_OnTaskEnd(p->taskid, p->user_context, p->user_id, p->error_type, p->error_code, p->profile);
            schedule = true;
        };

        WaitForRunJS(&data);
        return data.result;
    } else {
    	VarCache* cache_instance = VarCache::Singleton();
    	napi_env env = cache_instance->GetJSEnv();

    	napi_value jobj_cgiItem = JS_CallStaticMethodByName(env, "com.ohos.mars.stn.StnLogic.CgiProfile", "constructor", 0);
        if (nullptr == jobj_cgiItem) {
            //env->ThrowNew(env->FindClass("java/lang/RuntimeException"), "C2Java_OnTaskEnd: create jobject failed.");
            return -1;
        }

        uint64_t tls_start_time = profile.tls_handshake_successful_time == 0 ? 0 : profile.start_tls_handshake_time;

    	JS_SetAField(env, jobj_cgiItem, "taskStartTime", profile.start_time);
        JS_SetAField(env, jobj_cgiItem, "startConnectTime", profile.start_connect_time);
        JS_SetAField(env, jobj_cgiItem, "connectSuccessfulTime", profile.connect_successful_time);
        JS_SetAField(env, jobj_cgiItem, "startHandshakeTime",tls_start_time);
        JS_SetAField(env, jobj_cgiItem, "handshakeSuccessfulTime", profile.tls_handshake_successful_time);
        JS_SetAField(env, jobj_cgiItem, "startSendPacketTime", profile.start_send_packet_time);
        JS_SetAField(env, jobj_cgiItem, "startReadPacketTime", profile.start_read_packet_time);
        JS_SetAField(env, jobj_cgiItem, "readPacketFinishedTime", profile.read_packet_finished_time);

        napi_value _taskid = 0;
        napi_value _user_context = (napi_value)NULL;
        napi_value _error_type = 0;
        napi_value _error_code = 0;

        napi_create_uint32(env, taskid, &_taskid);
        napi_create_int32(env, error_type, &_error_type);
        napi_create_int32(env, error_code, &_error_code);
    	napi_value result = JS_CallStaticMethodByName(env, "com.ohos.mars.stn.StnLogic", "onTaskEnd", 5, _taskid, _user_context, _error_type, _error_code, jobj_cgiItem);

    	int32_t ret;
    	napi_status status = napi_get_value_int32(env, result, &ret);
    	return ret;
    }
};

typedef struct{
  ExecData base;
  const std::string& channel_id;
  uint32_t cmdid;
  uint32_t taskid;
  const AutoBuffer& body;
  const AutoBuffer& extend;
} OnPushData;

void C2JS_OnPush(const std::string& channel_id, uint32_t cmdid, uint32_t taskid, const AutoBuffer& body, const AutoBuffer& extend){
    xverbose_function();

    static bool schedule = true;
    xinfo2("enter C2JS_OnPush schedule:") << schedule;

    if(schedule) {
        OnPushData data = {NULL, channel_id, cmdid, taskid, body, extend};
        data.base.jsfn = [](void* data){
            OnPushData* p = (OnPushData*)data;
            schedule = false;
            C2JS_OnPush(p->channel_id, p->cmdid, p->taskid, p->body, p->extend);
            schedule = true;
        };

        WaitForRunJS(&data);
    } else {
    	VarCache* cache_instance = VarCache::Singleton();
    	napi_env env = cache_instance->GetJSEnv();

        napi_value _channel_id = NULL;
        napi_value _cmdid = NULL;
        napi_value _taskid = NULL;
    	napi_value _body = NULL;


        napi_create_string_utf8(env, channel_id.c_str(), channel_id.length(), &_channel_id);
        napi_create_uint32(env, cmdid, &_cmdid);
        napi_create_uint32(env, taskid, &_taskid);

    	if (body.Length() > 0) {
    		_body = JS_Buffer2JbyteArray(env, body);
    	} else {
    		xdebug2(TSF"the data.Lenght() < = 0");
    	}

    	napi_value value = JS_CallStaticMethodByName(env, "com.ohos.mars.stn.StnLogic", "onPush", 4, _channel_id, _cmdid, _taskid, _body);
    }
};

typedef struct{
  ExecData base;
  const std::string& host;
  std::vector<std::string> result;
} OnNewDnsData;

std::vector<std::string> C2JS_OnNewDns(const std::string& host){
	xverbose_function();

    static bool schedule = true;
    xinfo2("enter C2JS_OnNewDns schedule:") << schedule;

    if(schedule) {
        OnNewDnsData data = {NULL, host, {}};
        data.base.jsfn = [](void* data){
            OnNewDnsData* p = (OnNewDnsData*)data;
            schedule = false;
            p->result = C2JS_OnNewDns(p->host);
            schedule = true;
        };

        WaitForRunJS(&data);
        return data.result;
    } else {
        VarCache* cache_instance = VarCache::Singleton();
        napi_env env = cache_instance->GetJSEnv();

        std::vector<std::string> iplist;

        if (!host.empty()) {
        	napi_value ip_values = JS_CallStaticMethodByName(env, "com.ohos.mars.stn.StnLogic", "onNewDns", 1, &host);
        	if (ip_values != NULL) {
        		uint32_t arrayLength;
        		int status =  napi_get_array_length(env, ip_values, &arrayLength);

        		for (int idx = 0; idx < (int)arrayLength; ++idx) {
        			napi_value elemValue;
        			status = napi_get_element(env, ip_values, idx, &elemValue);
        			if (status != napi_ok) {
        				return iplist;
        			}
        			std::string elemStr;
        			status = GetNAPIStringValue(env, elemValue, elemStr);
        			if (status != napi_ok) {
        				return iplist;
        			}
        			iplist.push_back(elemStr);
        		}
        	}
        }
        else {
        	xerror2(TSF"host is empty");
        }

        return iplist;
    }
};


typedef struct{
  ExecData base;
  uint32_t taskid;
  void* const user_context;
  const std::string& user_id;
  AutoBuffer& outbuffer;
  AutoBuffer& extend;
  int& error_code;
  const int channel_select;
  const std::string& host;
  bool result;
} Req2BufData;

bool C2JS_Req2Buf(uint32_t taskid,  void* const user_context, const std::string& user_id, AutoBuffer& outbuffer,  AutoBuffer& extend, int& error_code, const int channel_select, const std::string& host){
    xverbose_function();

    static bool schedule = true;
    xinfo2("enter C2JS_Req2Buf schedule:") << schedule;

    if(schedule) {
        Req2BufData data = {NULL, taskid, user_context, user_id, outbuffer, extend, error_code, channel_select, host, false};
        data.base.jsfn = [](void* data){
            Req2BufData* p = (Req2BufData*)data;
            schedule = false;
            p->result = C2JS_Req2Buf(p->taskid, p->user_context, p->user_id, p->outbuffer, p->extend, p->error_code, p->channel_select, p->host);
            schedule = true;
        };

        WaitForRunJS(&data);
        return data.result;
    } else {
    	VarCache* cache_instance = VarCache::Singleton();
    	napi_env env = cache_instance->GetJSEnv();

        napi_value _taskid = NULL;
        napi_value _user_context = (napi_value)NULL;
        napi_value _channel_select = NULL;
        napi_value _host = NULL;

        napi_create_uint32(env, taskid, &_taskid);
        xinfo2("_taskid:") << _taskid;
        napi_create_int32(env, channel_select, &_channel_select);
        napi_create_string_utf8(env, host.c_str(), host.length()+1, &_host);

    	napi_value retValue = JS_CallStaticMethodByName(env, "com.ohos.mars.stn.StnLogic", "req2Buf", 4, _taskid, NULL, _channel_select, _host);

    	uint32_t arrayLength;
    	napi_status status =  napi_get_array_length(env, retValue, &arrayLength);
    	if (status != napi_ok || arrayLength != 3) {
            xinfo2("C2JS_Req2Buf return by napi_get_array_length error");
    		return false;
    	}

    	napi_value bValue;
        status = napi_get_element(env, retValue, 0, &bValue);
    	if (status != napi_ok) {
            xinfo2("C2JS_Req2Buf return by napi_get_element 0 error");
    		return false;
    	}
    	bool funcRetValue;
    	status = napi_get_value_bool(env, bValue, &funcRetValue);
        if (status != napi_ok || !funcRetValue) {
            xinfo2("C2JS_Req2Buf return by napi_get_element 0 error. status:%1, funcRetValue:%2", status, funcRetValue);
    		return false;
    	}

    	napi_value byte_array_output_stream_obj;
    	status = napi_get_element(env, retValue, 1, &byte_array_output_stream_obj);
    	if (status != napi_ok) {
            xinfo2("C2JS_Req2Buf return by napi_get_element 1 error. status:%1", status);
    		return false;
    	}

    	void* buffer = nullptr;
        size_t buffer_length = 0;
    	status = napi_get_arraybuffer_info(env, byte_array_output_stream_obj, &buffer, &buffer_length);
        if (status != napi_ok) {
            xinfo2("C2JS_Req2Buf return by napi_get_arraybuffer_info error. status:") << status;
    		return false;
    	}
        if (buffer != NULL) {
    		outbuffer.Write(buffer, buffer_length);
    		xinfo2("outbuffer.Write write buffer_length:") <<buffer_length;
    	} else {
    		xdebug2(TSF"the retByteArray is null");
    	}

    	napi_value errcode_array;
    	status = napi_get_element(env, retValue, 2, &errcode_array);
    	if (status != napi_ok) {
    		return false;
    	}

    	status =  napi_get_array_length(env, errcode_array, &arrayLength);
    	if (status != napi_ok || arrayLength <= 0) {
    		return false;
    	}

    	napi_value elemValue;
    	status = napi_get_element(env, errcode_array, 0, &elemValue);
    	if (status != napi_ok) {
    		return false;
    	}
    	int32_t intValue;
    	status = napi_get_value_int32(env, elemValue, &error_code);
    	if (status != napi_ok) {
    		return false;
    	}

    	return true;
    }
};


typedef struct{
  ExecData base;
  uint32_t taskid;
  void* const user_context;
  const std::string& user_id;
  const AutoBuffer& inbuffer;
  const AutoBuffer& extend;
  int& error_code;
  const int channel_select;
  int result;
} Buf2RespData;

int C2JS_Buf2Resp(uint32_t taskid, void* const user_context, const std::string& user_id, const AutoBuffer& inbuffer, const AutoBuffer& extend, int& error_code, const int channel_select){
    xverbose_function();

    static bool schedule = true;
    xinfo2("enter C2JS_Buf2Resp schedule:") << schedule;

    if(schedule) {
        Buf2RespData data = {NULL, taskid, user_context, user_id, inbuffer, extend, error_code, channel_select, 0};
        data.base.jsfn = [](void* data){
            Buf2RespData* p = (Buf2RespData*)data;
            schedule = false;
            p->result = C2JS_Buf2Resp(p->taskid, p->user_context, p->user_id, p->inbuffer, p->extend, p->error_code, p->channel_select);
            schedule = true;
        };

        WaitForRunJS(&data);
        return data.result;
    } else {
    	VarCache* cache_instance = VarCache::Singleton();
    	napi_env env = cache_instance->GetJSEnv();

    	napi_value resp_buf_jba = NULL;

        xinfo2("inbuffer.Length():") << inbuffer.Length();

    	if (inbuffer.Length() > 0) {
    		resp_buf_jba =  JS_Buffer2JbyteArray(env, inbuffer);
            xinfo2("resp_buf_jba") << resp_buf_jba;
    	} else {
    		xdebug2(TSF"the decodeBuffer.Lenght() <= 0");
    	}

        napi_value _taskid = NULL;
        napi_value _user_context = (napi_value)user_context;
        napi_value _channel_select = NULL;
        napi_create_uint32(env, taskid, &_taskid);
        napi_create_int32(env, channel_select, &_channel_select);

        xinfo2("calling JS_CallStaticMethodByName _taskid:%1, _user_context:%2, _channel_select:%3", _taskid, _user_context, _channel_select);
    	napi_value retValue = JS_CallStaticMethodByName(env, "com.ohos.mars.stn.StnLogic", "buf2Resp", 4, _taskid, NULL, resp_buf_jba, _channel_select);
        napi_status status = napi_get_value_int32(env, retValue, &error_code);
    	if (status != napi_ok) {
    		return -1;
    	}
        xinfo2("exit C2JS_Buf2Resp");

    	return error_code;
    }
}


typedef struct{
  ExecData base;
  const std::string& host;
  const std::string& user_id;
  bool result;
} MakesureAuthedData;


bool C2JS_MakesureAuthed(const std::string& host, const std::string& user_id){
    xverbose_function();

    static bool schedule = true;
    xinfo2("enter C2JS_MakesureAuthed schedule:") << schedule;

    if(schedule) {
        MakesureAuthedData data = {NULL, host, user_id, false};
        data.base.jsfn = [](void* data){
            MakesureAuthedData* p = (MakesureAuthedData*)data;
            schedule = false;
            p->result = C2JS_MakesureAuthed(p->host, p->user_id);
            schedule = true;
        };

        WaitForRunJS(&data);
        return data.result;
    } else {
       	VarCache* cache_instance = VarCache::Singleton();
    	napi_env env = cache_instance->GetJSEnv();

        napi_value _host = NULL;
        napi_create_string_utf8(env, host.c_str(), host.length(), &_host);

    	napi_value retValue = JS_CallStaticMethodByName(env, "com.ohos.mars.stn.StnLogic", "makesureAuthed", 1, _host);
    	bool ret;
    	napi_status status = napi_get_value_bool(env, retValue, &ret);

    	return ret;
    }
};


typedef struct{
  ExecData base;
  const std::string& channel_id;
  AutoBuffer& identify_buffer;
  AutoBuffer& buffer_hash;
  int32_t& cmdid;
  int result;
} GetLonglinkIdentifyCheckBufferData;

int C2JS_GetLonglinkIdentifyCheckBuffer(const std::string& channel_id, AutoBuffer& identify_buffer, AutoBuffer& buffer_hash, int32_t& cmdid){
    xverbose_function();

    static bool schedule = true;
    xinfo2("enter C2JS_GetLonglinkIdentifyCheckBuffer schedule:") << schedule;

    if(schedule) {
        GetLonglinkIdentifyCheckBufferData data = {NULL, channel_id, identify_buffer, buffer_hash, cmdid};
        data.base.jsfn = [](void* data){
            GetLonglinkIdentifyCheckBufferData* p = (GetLonglinkIdentifyCheckBufferData*)data;
            schedule = false;
            p->result = C2JS_GetLonglinkIdentifyCheckBuffer(p->channel_id, p->identify_buffer, p->buffer_hash, p->cmdid);
            schedule = true;
        };

        WaitForRunJS(&data);
        return data.result;
    } else {
        VarCache* cache_instance = VarCache::Singleton();
    	napi_env env = cache_instance->GetJSEnv();

    	napi_value byte_array_outputstream_obj;
    	napi_value byte_array_outputstream_hash;

        napi_value jcmdid_array;

    	int ret = 0;

        napi_value _channel_id = NULL;
        napi_create_string_utf8(env, channel_id.c_str(), channel_id.length(), &_channel_id);
    	napi_value retValue = JS_CallStaticMethodByName(env, "com.ohos.mars.stn.StnLogic", "getLongLinkIdentifyCheckBuffer", 1, _channel_id);	

    	uint32_t arrayLength;
    	napi_status status =  napi_get_array_length(env, retValue, &arrayLength);
    	if (status != napi_ok || arrayLength < 4) {
    		return -1;
    	}

    	napi_value oriRetValue;
    	status = napi_get_element(env,retValue, 0, &oriRetValue);
    	if (status != napi_ok) {
    		return -1;
    	}
    	status = napi_get_value_int32(env, oriRetValue, &ret);
    	if (status != napi_ok) {
    		return -1;
    	}
    	if (ret == kCheckNext || ret == kCheckNever)
    	{
    		xwarn2(TSF"getLongLinkIdentifyCheckBuffer uin == 0, not ready");		
    		return ret;
    	}

    	status = napi_get_element(env, retValue, 1, &byte_array_outputstream_obj);
    	if (status != napi_ok) {
    		return -1;
    	}

    	status = napi_get_element(env, retValue, 2, &byte_array_outputstream_hash);
    	if (status != napi_ok) {
    		return -1;
    	}

    	status = napi_get_element(env, retValue, 3, &jcmdid_array);
    	if (status != napi_ok) {
    		return -1;
    	}


    	status =  napi_get_array_length(env, byte_array_outputstream_hash, &arrayLength);
    	if (status != napi_ok) {
    		return -1;
    	}
    	napi_value elemValue;

    	for (int idx = 0; idx < arrayLength; ++idx) {
    		unsigned char ch;

    		status = napi_get_element(env, byte_array_outputstream_obj, idx, &elemValue);
    		if (status != napi_ok) {
    			return -1;
    		}
    		int32_t intValue;
    		status = napi_get_value_int32(env, elemValue, &intValue);
    		if (status != napi_ok) {
    			return -1;
    		}
    		ch = (unsigned char)intValue;
    		identify_buffer.Write(ch);
    	}

    	status =  napi_get_array_length(env, byte_array_outputstream_hash, &arrayLength);
    	if (status != napi_ok) {
    		return -1;
    	}

    	for (int idx = 0; idx < arrayLength; ++idx) {
    		unsigned char ch;

    		status = napi_get_element(env, byte_array_outputstream_hash, idx, &elemValue);
    		if (status != napi_ok) {
    			return -1;
    		}
    		int32_t intValue;
    		status = napi_get_value_int32(env, elemValue, &intValue);
    		if (status != napi_ok) {
    			return -1;
    		}
    		ch = (unsigned char)intValue;
    		buffer_hash.Write(ch);
    	}

    	status =  napi_get_array_length(env, jcmdid_array, &arrayLength);
    	if (status != napi_ok || arrayLength <= 0) {
    		return -1;
    	}

    	status = napi_get_element(env, jcmdid_array, 0, &elemValue);
    	if (status != napi_ok || arrayLength <= 0) {
    		return -1;
    	}

    	status = napi_get_value_int32(env, elemValue, &cmdid);
    	if (status != napi_ok || arrayLength <= 0) {
    		return -1;
    	}
    	return ret;
    }
};


typedef struct{
  ExecData base;
  const std::string& channel_id;
  const AutoBuffer& response_buffer;
  const AutoBuffer& identify_buffer_hash;
  bool result;
} OnLonglinkIdentifyResponseData;

bool C2JS_OnLonglinkIdentifyResponse(const std::string& channel_id, const AutoBuffer& response_buffer, const AutoBuffer& identify_buffer_hash){
    xverbose_function();

    static bool schedule = true;
    xinfo2("enter C2JS_OnLonglinkIdentifyResponse schedule:") << schedule;

    if(schedule) {
        OnLonglinkIdentifyResponseData data = {NULL, channel_id, response_buffer, identify_buffer_hash};
        data.base.jsfn = [](void* data){
            OnLonglinkIdentifyResponseData* p = (OnLonglinkIdentifyResponseData*)data;
            schedule = false;
            p->result = C2JS_OnLonglinkIdentifyResponse(p->channel_id, p->response_buffer, p->identify_buffer_hash);
            schedule = true;
        };

        WaitForRunJS(&data);
        return data.result;
    } else {
    	VarCache* cache_instance = VarCache::Singleton();
    	napi_env env = cache_instance->GetJSEnv();

    	napi_value data_jba = NULL;

    	if (response_buffer.Length() > 0) {
    		data_jba = JS_Buffer2JbyteArray(env, response_buffer);
    	} else {
    		xdebug2(TSF"the respbuffer.Lenght() < = 0");
    	}

    	napi_value hash_jba = NULL;
    	if (identify_buffer_hash.Length() > 0) {
    		hash_jba = JS_Buffer2JbyteArray(env, identify_buffer_hash);
    	} else {
    		xdebug2(TSF"the hashCodeBuffer.Lenght() < = 0");
    	}

        napi_value _channel_id = NULL;
        napi_create_string_utf8(env, channel_id.c_str(), channel_id.length(), &_channel_id);

    	napi_value retValue = JS_CallStaticMethodByName(env, "com.ohos.mars.stn.StnLogic", "onLongLinkIdentifyResp", 3, _channel_id, data_jba, hash_jba);
    	bool ret;	
    	napi_status status = napi_get_value_bool(env, retValue, &ret);
    	if (status != napi_ok) {
    		return false;
    	}
        return ret;
    }
}


typedef struct{
  ExecData base;
  ssize_t send;
  ssize_t recv;
} TrafficDataData;

void C2JS_TrafficData(ssize_t send, ssize_t recv) {
    xverbose_function();

    static bool schedule = true;
    xinfo2("enter C2JS_TrafficData schedule:") << schedule;

    if(schedule) {
        TrafficDataData data = {NULL, send, recv};
        data.base.jsfn = [](void* data) {
            TrafficDataData* p = (TrafficDataData*)data;
            schedule = false;
            C2JS_TrafficData(p->send, p->recv);
            schedule = true;
        };

        WaitForRunJS(&data);
    } else {
    	VarCache* cache_instance = VarCache::Singleton();
    	napi_env env = cache_instance->GetJSEnv();

    	napi_value _send = NULL;
        napi_value _recv = NULL;
        napi_create_int64(env, send, &_send);
        napi_create_int64(env, recv, &_recv);
    	JS_CallStaticMethodByName(env, "com.ohos.mars.stn.StnLogic", "trafficData", 2, _send, _recv);
    }
}


typedef struct{
  ExecData base;
  int all_connstatus;
  int longlink_connstatus;
} ReportConnectStatusData;

void C2JS_ReportConnectStatus(int all_connstatus, int longlink_connstatus){
    xverbose_function();

    static bool schedule = true;
    xinfo2("enter C2JS_ReportConnectStatus schedule:") << schedule;

    if(schedule) {
        ReportConnectStatusData data = {NULL, all_connstatus, longlink_connstatus};
        data.base.jsfn = [](void* data){
            ReportConnectStatusData* p = (ReportConnectStatusData*)data;
            schedule = false;
            C2JS_ReportConnectStatus(p->all_connstatus, p->longlink_connstatus);
            schedule = true;
        };

        WaitForRunJS(&data);
    } else {
       	VarCache* cache_instance = VarCache::Singleton();
    	napi_env env = cache_instance->GetJSEnv();

    	napi_value _all_connstatus = NULL;
        napi_value _longlink_connstatus = NULL;
        napi_create_int32(env, all_connstatus, &_all_connstatus);
        napi_create_int32(env, longlink_connstatus, &_longlink_connstatus);

    	JS_CallStaticMethodByName(env, "com.ohos.mars.stn.StnLogic", "reportConnectStatus", 2, _all_connstatus, _longlink_connstatus);
        xdebug2(TSF"all_connstatus = %0, longlink_connstatus = %_", _all_connstatus, _longlink_connstatus);
    }
};

void reportCrashStatistics(const char* _raw, const char* _type)
{
}


typedef struct{
  ExecData base;
} RequestSyncData;

void C2JS_RequestSync() {
    xverbose_function();

    static bool schedule = true;
    xinfo2("enter C2JS_ReportConnectStatus schedule:") << schedule;

    if(schedule) {
        RequestSyncData data;
        data.base.jsfn = [](void* data){
            RequestSyncData* p = (RequestSyncData*)data;
            schedule = false;
            C2JS_RequestSync();
            schedule = true;
        };

        WaitForRunJS(&data);
    } else {
        VarCache* cache_instance = VarCache::Singleton();
    	napi_env env = cache_instance->GetJSEnv();
    	JS_CallStaticMethodByName(env, "com.ohos.mars.stn.StnLogic", "requestDoSync", 0);
    }
}


typedef struct{
  ExecData base;
  std::vector<std::string>& hostlist;
} RequestNetCheckShortLinkHostsData;

void C2JS_RequestNetCheckShortLinkHosts(std::vector<std::string>& hostlist){
	xverbose_function();

    static bool schedule = true;
    xinfo2("enter C2JS_ReportConnectStatus schedule:") << schedule;

    if(schedule) {
        RequestNetCheckShortLinkHostsData data = {NULL, hostlist};
        data.base.jsfn = [](void* data){
            RequestNetCheckShortLinkHostsData* p = (RequestNetCheckShortLinkHostsData*)data;
            schedule = false;
            C2JS_RequestNetCheckShortLinkHosts(p->hostlist);
            schedule = true;
        };

        WaitForRunJS(&data);
    } else {
    	VarCache* cache_instance = VarCache::Singleton();
    	napi_env env = cache_instance->GetJSEnv();
    	napi_value jobj_arr = JS_CallStaticMethodByName(env, "com.ohos.mars.stn.StnLogic", "requestNetCheckShortLinkHosts", 0); 

    	int status;
    	if (jobj_arr != NULL) {
    		uint32_t arrayLength;
    		status =  napi_get_array_length(env, jobj_arr, &arrayLength);

    		for (int idx = 0; idx < (int)arrayLength; ++idx) {
    			napi_value elemValue;
    			status = napi_get_element(env, jobj_arr, idx, &elemValue);
    			if (status != napi_ok) {
    				return;
    			}
    			std::string elemStr;
    			status = GetNAPIStringValue(env, elemValue, elemStr);
    			if (status != napi_ok) {
    				return;
    			}
    			hostlist.push_back(elemStr);
    		}
    	}
    }
}


typedef struct{
  ExecData base;
  const TaskProfile& task_profile;
} ReportTaskProfileData;

void C2JS_ReportTaskProfile(const TaskProfile& task_profile){
	xverbose_function();

    static bool schedule = true;
    xinfo2("enter C2JS_ReportTaskProfile schedule:") << schedule;

    if(schedule) {
        ReportTaskProfileData data = {NULL, task_profile};
        data.base.jsfn = [](void* data){
            ReportTaskProfileData* p = (ReportTaskProfileData*)data;
            schedule = false;
            C2JS_ReportTaskProfile(p->task_profile);
            schedule = true;
        };

        WaitForRunJS(&data);
    } else {
    	VarCache* cache_instance = VarCache::Singleton();
    	napi_env env = cache_instance->GetJSEnv();

    	XMessage profile_json;
    	profile_json << "{";
    	profile_json << "\"taskId\":" << task_profile.task.taskid;
    	profile_json << ",\"cmdId\":" << task_profile.task.cmdid;
    	profile_json << ",\"cgi\":\"" << task_profile.task.cgi << "\"";
    	profile_json << ",\"startTaskTime\":" << task_profile.start_task_time;
    	profile_json << ",\"endTaskTime\":" << task_profile.end_task_time;
    	profile_json << ",\"dyntimeStatus\":" << task_profile.current_dyntime_status;
    	profile_json << ",\"errCode\":" << task_profile.err_code;
    	profile_json << ",\"errType\":" << task_profile.err_type;
    	profile_json << ",\"channelSelect\":" << task_profile.link_type;
    	profile_json << ",\"historyNetLinkers\":[";
    	std::vector<TransferProfile>::const_iterator iter = task_profile.history_transfer_profiles.begin();
    	for (; iter != task_profile.history_transfer_profiles.end(); ) {
    		const ConnectProfile& connect_profile = iter->connect_profile;
    		profile_json << "{";
    		profile_json << "\"startTime\":" << connect_profile.start_time;
    		profile_json << ",\"dnsTime\":" << connect_profile.dns_time;
    		profile_json << ",\"dnsEndTime\":" << connect_profile.dns_endtime;
    		profile_json << ",\"connTime\":" << connect_profile.conn_time;
    		profile_json << ",\"connErrCode\":" << connect_profile.conn_errcode;
    		profile_json << ",\"tryIPCount\":" << connect_profile.tryip_count;
    		profile_json << ",\"ip\":\"" << connect_profile.ip << "\"";
    		profile_json << ",\"port\":" << connect_profile.port;
    		profile_json << ",\"host\":\"" << connect_profile.host << "\"";
    		profile_json << ",\"ipType\":" << connect_profile.ip_type;
    		profile_json << ",\"disconnTime\":" << connect_profile.disconn_time;
    		profile_json << ",\"disconnErrType\":" << connect_profile.disconn_errtype;
    		profile_json << ",\"disconnErrCode\":" << connect_profile.disconn_errcode;

    		profile_json << "}";
    		if (++iter != task_profile.history_transfer_profiles.end()) {
    			profile_json << ",";
    		}
    		else {
    			break;
    		}
    	}
    	profile_json << "]}";
    	std::string report_task_str = profile_json.String();

        napi_value _report_task_str = NULL;
        napi_create_string_utf8(env, report_task_str.c_str(), report_task_str.length(), &_report_task_str);

    	JS_CallStaticMethodByName(env, "com.ohos.mars.stn.StnLogic", "reportTaskProfile", 1, _report_task_str);
    }
}
}
}
